package org.mmtk.plan.scale.colors;

import org.mmtk.plan.scale.ScaleMarkSweepSpace;
import org.mmtk.utility.Log;
import org.mmtk.utility.options.Options;
import org.mmtk.vm.VM;
import org.vmmagic.pragma.Uninterruptible;
import org.vmmagic.unboxed.ObjectReference;

@Uninterruptible
public final class CMSweeper extends ScaleMarkSweepSpace.Sweeper {
	
	private long invalidObjects;
	private long totalObjects;
	private long coloredLiveObjects;
	private long coloredDeadObjects;
	
	public void start() {
		invalidObjects = 0;
		totalObjects = 0;
		coloredLiveObjects = 0;
		coloredDeadObjects = 0;
	}
	
	public void end() {
		Log.write("sweepCell.end - totalObjects: ");
		Log.write(totalObjects);
		Log.write(", invalidObjects: ");
		Log.write(invalidObjects);
		Log.write(", coloredLiveObjects: ");
		Log.write(coloredLiveObjects);
		Log.write(", coloredDeadObjects: ");
		Log.writeln(coloredDeadObjects);
		Log.flush();
	}
	
	/**
	 * Called for live objects in heap
	 * 
	 * always return false to signify that live objects remains live after this
	 * operation
	 */
	public boolean sweepCell(ObjectReference object) {
		if (Options.scaleDebug.getValue() > 4) {
			Log.write("sweepCell - enter, obj=");
			Log.flush();
			VM.objectModel.dumpObject(object);
			Log.flush();
		}

		this.totalObjects++;

		if (!VM.objectModel.validRef(object)) {
			this.invalidObjects++;
			//return false;
		}

		ObjectReference colorMark = VM.objectModel.getKathy(object);
		if (colorMark != ObjectReference.nullReference()) {
			if (Options.verbose.getValue() > 4) {
				Log.write("sweepCell - colored object=");
				Log.write(object);
				Log.write(", color=");
				Log.writeln(colorMark);
				Log.flush();
			}
			Color color = Color.getColor(colorMark);
			if (color == null) {
				// sanity
				if (Options.scaleDebug.getValue() > 3) {
					Log.writeln("sweepCell - color is null !!!");
					Log.flush();
					// VM.objectModel.dumpObject(object);
				}
			} else {
				if (Options.scaleDebug.getValue() > 4) {
					Log.write("sweepCell: color=");
					color.dump();
				}
				if (color.isLive()) {
					this.coloredLiveObjects++;
					SColors.scaleSpace.markObject(object);
				} else {
					this.coloredDeadObjects++;
					SColors.scaleSpace.writeAllocState(object);
				}
			}
			VM.objectModel.setKathy(object, ObjectReference.nullReference());
		}

		if (Options.scaleDebug.getValue() > 4) {
			Log.write("sweepCell - exit ");
			Log.flush();
			VM.objectModel.dumpObject(object);
			Log.flush();
		}

		return true;
	}
}
